import BaseCellComponent from "./BaseCellComponent";

const {ccclass, property} = cc._decorator;
/*
*ClassName:BaseScrollViewComponent
*Description:固定大小的列表组件
*Date:2019/5/19 21:12
*/
@ccclass
export default class BaseScrollViewComponent extends cc.ScrollView {

    @property(cc.Prefab)
    cellItemPrefab: cc.Prefab = null;

    @property(cc.ScrollView)
    scrollView: cc.ScrollView = null;

    @property(cc.Node)
    view: cc.Node = null;

    @property({tooltip: "是否是水平滚动"} || cc.Boolean)
    _horizontal: boolean = false;

    @property({tooltip: "是否是水平滚动", override: true})
    set horizontal(value) {
        this._horizontal = value;
        this._vertical = !value;
    }

    get horizontal() {
        return this._horizontal;
    }

    @property({tooltip: "是否是竖直滚动"} || cc.Boolean)
    _vertical: boolean = true;

    @property({tooltip: "是否是竖直滚动", override: true})
    set vertical(value) {
        this._horizontal = !value;
        this._vertical = value;
    }

    get vertical() {
        return this._vertical;
    }

    @property(cc.Float)
    spacing: number = 10;

    /** 存放 cell 的列表 */
    private cellItemList: cc.Node[] = [];

    /** cell 大小 */
    private cellItemTempSize: cc.Size = null;

    /** 滑动之前的 content 的位置 */
    private lastContentPosition: cc.Vec2 = cc.v2(0, 0);

    private cellDataList: any[] = [];

    private isUpdateFrame: boolean = true;
    private cellKey: string = "cellKey";
    private isDisableDeleteItem: boolean = false;//是否destroy是回收元素
    /**
     * 对象池
     * */
    private item_pool: cc.NodePool = null;
    private isCreatePool: boolean = false;


    onDisable() {
        if (!this.isDisableDeleteItem) {
            return;
        }
        this.onClearCellList();
    }

    /** 初始化UI */
    onInitUI() {
        // TODO 由子类继承，并实现
    }

    /***
     * 初始化cellData的数据
     * @param {} cellDataList 元素的数据数组
     * @param {} isDisableDeleteItem 是否disable是回收对象
     */
    public onInitCellDataList(cellDataList: any[], isDisableDeleteItem: boolean = false) {
        this.onClearCellList();
        this.createPrefabPool();
        this.isDisableDeleteItem = isDisableDeleteItem;
        this.scrollView.content.on("position-changed", this._updateContentView);
        this.cellDataList = cellDataList;
        this.onCreateCellList();
    }

    /***
     * 初始化起点  initIndex显示为第一个
     * @param {number} initIndex
     */
    public onSetInitPos(initIndex: number) {
        if (this._vertical) {
            this.scrollView.content.setPosition(0, (this.cellItemTempSize.height + this.spacing) * (initIndex - 1));
        } else {
            this.scrollView.content.setPosition((this.cellItemTempSize.width + this.spacing) * (initIndex - 1), 0);
        }
    }

    /**删除某一个元素再进行重新排列*/
    public onDeleteOneCellData(index: number) {
        this.cellDataList.splice(index, 1);
        this.onInitCellDataList(this.cellDataList);
    }

    /***
     * 清空列表
     */
    public onClearCellList() {
        if (this.scrollView == null) {
            return;
        }
        if (this.scrollView.content == null) {
            return;
        }
        if (this.scrollView.content.children == null) {
            return;
        }
        this.stopAutoScroll();
        this.scrollView.content.off("position-changed", this._updateContentView);
        // console.log('y =',  this.scrollView.content.y ,'/height = ', this.scrollView.content.height);
        if (this._vertical) {
            this.unschedule(this._updateVerticalContentView);
        } else {
            this.unschedule(this._updateHorizontalContentView);
        }

        this.isUpdateFrame = true;
        this.cellItemTempSize = null;

        let len = this.scrollView.content.children.length;
        for (let i = 0; i < len; ++i) {
            let prefab = this.scrollView.content.children[i];
            if (prefab) {
                this.item_pool.put(prefab);
                i--;
            }
        }
        this.cellDataList = [];
        this.cellItemList = [];
        // console.log(this.scrollView.content.childrenCount);
        if (this._vertical) {
            this.scrollView.content.height = 0;
            this.scrollView.content.y = 0;
        } else {
            this.scrollView.content.width = 0;
            this.scrollView.content.x = 0;
        }
    }


    /** 创建cell List列表 */
    private onCreateCellList() {
        if (this._vertical) {
            this._createVerticalCellList();
        } else {
            this._createHorizontalCellList();
        }
    }

    /***
     * 取item
     * @returns {cc.Node}
     */
    private getCellPrefab(): cc.Node {
        let newNode: cc.Node = null;
        if (this.item_pool.size() > 0) {
            newNode = this.item_pool.get();
        } else {
            newNode = cc.instantiate(this.cellItemPrefab);
        }
        newNode.parent = this.scrollView.content;
        newNode.active = true;
        return newNode;
    }

    /***
     * item pool
     */
    private createPrefabPool(): void {
        if (this.isCreatePool) {
            return;
        }
        this.isCreatePool = true;
        if (this.scrollView == null) {
            this.scrollView = this;
        }
        if (this.scrollView.content == null) {
            this.scrollView.content = this.node.children[0].children[0];
        }
        if (this.view == null) {
            this.view = this.node.children[0];
        }

        this._setNodeAnchor();

        this.item_pool = new cc.NodePool();
        let prefab = cc.instantiate(this.cellItemPrefab);
        let count = 5;
        for (let i = 0; i < count; ++i) {
            this.item_pool.put(prefab);
        }
    }

    private _setNodeAnchor() {
        if (this._vertical) {
            this.node.anchorX = 0.5;
            this.view.anchorX = 0.5;
            this.scrollView.content.anchorX = 0.5;
            this.cellItemPrefab.data.anchorX = 0.5;
        } else {
            this.node.anchorX = 0;
            this.view.anchorX = 0;
            this.scrollView.content.anchorX = 0;
            this.cellItemPrefab.data.anchorX = 0;
        }
        this.node.anchorY = 1;
        this.view.anchorY = 1;
        this.scrollView.content.anchorY = 1;
        this.cellItemPrefab.data.anchorY = 1;
    }

    private _createVerticalCellList() {
        let count = 10;
        for (let i = 0; i < this.cellDataList.length; i++) {
            if (i > count - 1) {
                return;
            }
            let node = this.getCellPrefab();
            if (i == 0) {
                this.cellItemTempSize = node.getContentSize();
                count = Math.ceil(this.node.height / node.height) * 2;
                let height = this.cellDataList.length * (this.cellItemTempSize.height + this.spacing);
                this.scrollView.content.setContentSize(cc.size(this.scrollView.content.width, height));
            }

            node[this.cellKey] = i;

            this.cellItemList.push(node);
            let logicComponent: BaseCellComponent = this.cellItemList[i].getComponent(this.cellItemPrefab.name);
            if (logicComponent && logicComponent.UpdateViewModel) {
                logicComponent.UpdateViewModel(this.cellDataList[i], i);
            }

            node.y = -i * (this.cellItemTempSize.height + this.spacing);
        }
    }

    private _createHorizontalCellList() {
        let count: number = 10;
        for (let i = 0; i < this.cellDataList.length; i++) {
            if (i > count - 1) {
                return;
            }
            let node: cc.Node = this.getCellPrefab();
            if (i == 0) {
                this.cellItemTempSize = node.getContentSize();
                count = Math.ceil(this.node.width / node.width) * 2;
                let width = this.cellDataList.length * (this.cellItemTempSize.width + this.spacing);
                this.scrollView.content.setContentSize(cc.size(width, this.scrollView.content.height));
            }

            node[this.cellKey] = i;

            this.cellItemList.push(node);

            let logicComponent: BaseCellComponent = this.cellItemList[i].getComponent(this.cellItemPrefab.name);
            if (logicComponent && logicComponent.UpdateViewModel) {
                logicComponent.UpdateViewModel(this.cellDataList[i], i);
            }
            node.x = (this.cellItemTempSize.width + this.spacing) * i;
        }
    }

    private _getPositionInView(item: cc.Node) {
        let worldPos = item.parent.convertToWorldSpaceAR(item.position);
        let viewPos = this.node.convertToNodeSpaceAR(worldPos);
        return viewPos;
    }

    private _updateContentView = () => {
        if (this._vertical) {
            if (this.isUpdateFrame) {
                this.isUpdateFrame = false;
                this.scheduleOnce(this._updateVerticalContentView.bind(this), 0);
            }
        } else {
            if (this.isUpdateFrame) {
                this.isUpdateFrame = false;
                this.scheduleOnce(this._updateHorizontalContentView.bind(this), 0);
            }
        }
    }

    private _updateVerticalContentView() {
        let isDown = this.scrollView.content.y < this.lastContentPosition.y;

        let offsetY = (this.cellItemTempSize.height + this.spacing) * this.cellItemList.length;
        let offset = offsetY / 4;
        let newY = 0;

        for (let i = 0; i < this.cellItemList.length; i++) {
            let viewPos = this._getPositionInView(this.cellItemList[i]);
            if (isDown) {
                newY = this.cellItemList[i].y + offsetY;
                if (viewPos.y < -(offset * 3) && newY <= 0) {
                    this.cellItemList[i].y = newY;
                    let idx = this.cellItemList[i][this.cellKey] - this.cellItemList.length;
                    let logicComponent: BaseCellComponent = this.cellItemList[i].getComponent(this.cellItemPrefab.name);
                    if (logicComponent && logicComponent.UpdateViewModel) {
                        logicComponent.UpdateViewModel(this.cellDataList[idx], idx);
                    }
                    this.cellItemList[i][this.cellKey] = idx;
                }
            } else {
                newY = this.cellItemList[i].y - offsetY;
                if (viewPos.y > offset && newY > -this.scrollView.content.height) {

                    this.cellItemList[i].y = newY;
                    let idx = this.cellItemList[i][this.cellKey] + this.cellItemList.length;
                    let logicComponent: BaseCellComponent = this.cellItemList[i].getComponent(this.cellItemPrefab.name);
                    if (logicComponent && logicComponent.UpdateViewModel) {
                        logicComponent.UpdateViewModel(this.cellDataList[idx], idx);
                    }
                    this.cellItemList[i][this.cellKey] = idx;
                }
            }
        }

        this.lastContentPosition = this.scrollView.content.position;
        this.isUpdateFrame = true;
    }

    private _updateHorizontalContentView() {
        let isLeft = this.scrollView.content.x < this.lastContentPosition.x;

        let offsetX = (this.cellItemTempSize.width + this.spacing) * this.cellItemList.length;
        let offset = offsetX / 4;
        let newX = 0;

        for (let i = 0; i < this.cellItemList.length; i++) {
            let viewPos = this._getPositionInView(this.cellItemList[i]);
            if (isLeft) {
                newX = this.cellItemList[i].x + offsetX;
                if (viewPos.x < -offset && newX < this.scrollView.content.width) {
                    this.cellItemList[i].x = newX;
                    let idx = this.cellItemList[i][this.cellKey] + this.cellItemList.length;
                    let logicComponent: BaseCellComponent = this.cellItemList[i].getComponent(this.cellItemPrefab.name);
                    if (logicComponent && logicComponent.UpdateViewModel) {
                        logicComponent.UpdateViewModel(this.cellDataList[idx], idx);
                    }
                    this.cellItemList[i][this.cellKey] = idx;
                }
            } else {
                newX = this.cellItemList[i].x - offsetX;
                if (viewPos.x > offset * 3 && newX >= 0) {

                    this.cellItemList[i].x = newX;
                    let idx = this.cellItemList[i][this.cellKey] - this.cellItemList.length;
                    let logicComponent: BaseCellComponent = this.cellItemList[i].getComponent(this.cellItemPrefab.name);
                    if (logicComponent && logicComponent.UpdateViewModel) {
                        logicComponent.UpdateViewModel(this.cellDataList[idx], idx);
                    }
                    this.cellItemList[i][this.cellKey] = idx;
                }
            }
        }

        this.lastContentPosition = this.scrollView.content.position;
        this.isUpdateFrame = true;
    }

}